﻿using ExpressionDemo.Entity;
using ExpressionTreeToString;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.Linq;
using System.Linq.Expressions;
using static System.Linq.Expressions.Expression;

namespace ExpressionDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
          using(SqlContext contxt =  new SqlContext())
            {
                //var blog = new Blog()
                //{
                //    Rating = 3,
                //    Url = "http://www.baidu.com"
                //};

                //var post1 = new Post() { Content = "this is goold", Title = "好文章",Blog = blog};
                //var post2 = new Post() { Content = "wow she is a petty girl", Title = "he is a buffer man",Blog = blog };
                //contxt.Add<Blog>(blog);
                //contxt.Add<Post>(post1);
                //contxt.Add<Post>(post2);
                //contxt.SaveChanges();

                //Expression<Func<Blog, bool>> exp = b => b.Url == "http";
                //Func<Blog, bool> func = b => b.Rating > 5;
                //Console.WriteLine(exp.ToString("Factory methods", "C#"));
                //var blogs = contxt.Blogs.Where(exp);
                //foreach(var item in blogs)
                //{
                //    Console.WriteLine($"Rating:{item.Rating},Url:{item.Url}");
                //}

                var blogs = QueryBlog("Rating", "abc");
                foreach (var item in blogs)
                {
                    Console.WriteLine($"Rating:{item.Rating},Url:{item.Url}");
                }
                Console.ReadKey();
            }
        }

        public static IEnumerable<Blog> QueryBlog(string propertyName, object value)
        {
            var b = Parameter(typeof(Blog), "b");
            var propertyInfo = typeof(Blog).GetProperty(propertyName);
            if(propertyInfo != null )
            {
                Type proType = propertyInfo.PropertyType;
                Expression body;
                var left = MakeMemberAccess(b, propertyInfo);
                var right = Constant(System.Convert.ChangeType(value, proType));
                if (proType.IsPrimitive)
                {
                    body = Equal(left, right);
                }
                else
                {
                    body = MakeBinary(ExpressionType.Equal, left, right, false, typeof(string).GetMethod("op_Equality"));
                }
                var exp = Lambda<Func<Blog, bool>>(body, b);
                using (var db = new SqlContext())
                {
                    var list = db.Blogs.Where(exp).ToList();
                    return list;
                }
            }
            else
            {
                return new List<Blog>();
            }
          
        }
    }
}